home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 2.toast / pc / sample code / quicktime / quicktime vr / vrscript.win / feature files / vr3dtexture.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  9.7 KB  |  327 lines

  1. //////////
  2. //
  3. //    File:        VR3DTexture.c
  4. //
  5. //    Contains:    Support for adding a QuickTime movie or a picture as a texture on a QD3D object.
  6. //
  7. //    Written by:    Tim Monroe
  8. //                Parts modeled on BoxMoov code by Rick Evans and Robert Dierkes.
  9. //
  10. //    Copyright:    © 1996-1998 by Apple Computer, Inc., all rights reserved.
  11. //
  12. //    Change History (most recent first):
  13. //
  14. //       <8>         04/21/98    rtm        changed all occurrences of gw->portPixMap to GetGWorldPixMap(gw),
  15. //                                    to prevent crashes reported on Windows
  16. //       <7>         03/09/98    rtm        changed PICT-specific code to use the graphics importer routines;
  17. //                                    now we can open any image file format supported by QuickTime;
  18. //                                    incorporated code previously in the file VR3DObjects.c, in the routines
  19. //                                    VR3DObjects_LoadEmbeddedMovie and VR3DObjects_LoopEmbeddedMovie
  20. //       <6>         01/28/98    rtm        changed NewGWorld calls to QTNewGWorld
  21. //       <5>         01/27/98    rtm        made minor changes to VR3DTexture_Delete
  22. //       <4>         05/02/97    rtm        added fMediaHandler field to textures, for movies with sound
  23. //       <3>         01/14/97    rtm        added support for PICT textures
  24. //       <2>         12/17/96    rtm        modified VR3DTexture_AddToGroup to replace a texture shader
  25. //       <1>         12/16/96    rtm        first file; revised to personal coding style
  26. //       
  27. //////////
  28.  
  29. // header files
  30. #include <QuickDraw.h>
  31. #include <Resources.h>
  32.  
  33. #include <QD3D.h>
  34. #include <QD3DGroup.h>
  35. #include <QD3DShader.h>
  36. #include <QD3DSet.h>
  37.  
  38. #include "VR3DTexture.h"
  39. #include "VR3DObjects.h"
  40. #include "QTUtilities.h"
  41. #include "QTVRUtilities.h"
  42.  
  43.  
  44. //////////
  45. //
  46. // VR3DTexture_New
  47. // Create a new texture from a QuickTime movie or PICT file.
  48. //
  49. //////////
  50.  
  51. TextureHdl VR3DTexture_New (char *thePathName, Boolean isTextureMovie)
  52. {
  53.     FSSpec                        myFSSpec;
  54.     unsigned long                myPictMapAddr;
  55.     unsigned long                 myPictRowBytes;
  56.     GWorldPtr                     myGWorld;
  57.     PixMapHandle                 myPixMap;
  58.     GDHandle                    myOldGD;
  59.     GWorldPtr                    myOldGW;
  60.     Rect                        myBounds;
  61.     TQ3StoragePixmap            *myStrgPMapPtr;
  62.     TextureHdl                    myTexture = NULL;
  63.     GraphicsImportComponent        myImporter = NULL;
  64.     short                        myMovieFileRef;
  65.     QDErr                        myErr = noErr;
  66.  
  67.     myTexture = (TextureHdl)NewHandleClear(sizeof(Texture));
  68.     if (myTexture == NULL)
  69.         return(myTexture);
  70.         
  71.     HLock((Handle)myTexture);
  72.  
  73.     // save the current port
  74.     GetGWorld(&myOldGW, &myOldGD);
  75.         
  76.     FSMakeFSSpec(0, 0L, c2pstr(thePathName), &myFSSpec);
  77.  
  78.     if (isTextureMovie) {
  79.         // open the movie and store its address in our data structure
  80.         myErr = OpenMovieFile(&myFSSpec, &myMovieFileRef, fsRdPerm);
  81.         if (myErr != noErr)
  82.             goto bail;
  83.  
  84.         myErr = NewMovieFromFile(&(**myTexture).fMovie, myMovieFileRef, NULL, (StringPtr)NULL, newMovieActive, NULL);
  85.         if (myErr != noErr)
  86.             goto bail;
  87.  
  88.         if (myMovieFileRef != 0)
  89.             CloseMovieFile(myMovieFileRef);
  90.             
  91.         SetMovieMatrix((**myTexture).fMovie, NULL);
  92.         MacSetRect(&myBounds, 0, 0, 128, 128);
  93.         SetMovieBox((**myTexture).fMovie, &myBounds);
  94.  
  95.         // get the sound media handler for movies with sound
  96.         if (QTUtils_IsMediaTypeInMovie((**myTexture).fMovie, SoundMediaType) || QTUtils_IsMediaTypeInMovie((**myTexture).fMovie, MusicMediaType))
  97.             (**myTexture).fMediaHandler = QTUtils_GetSoundMediaHandler((**myTexture).fMovie);
  98.         
  99.         // create a new offscreen graphics world (into which we will draw the movie)
  100.         myErr = QTNewGWorld(&myGWorld, kOffscreenPixelType, &myBounds, NULL, NULL, kICMTempThenAppMemory);
  101.         if (myErr != noErr) {
  102.             StopMovie((**myTexture).fMovie);
  103.             DisposeMovie((**myTexture).fMovie);
  104.             (**myTexture).fMovie = NULL;
  105.             goto bail;
  106.         }
  107.     } else {
  108.         // get a graphics importer for the image file
  109.         myErr = GetGraphicsImporterForFile(&myFSSpec, &myImporter);
  110.         if (myErr != noErr)
  111.             goto bail;
  112.         
  113.         // determine the natural size of the image
  114.         myErr = GraphicsImportGetNaturalBounds(myImporter, &myBounds);
  115.         if (myErr != noErr)
  116.             goto bail;
  117.             
  118.         // create a new offscreen graphics world (into which we will draw the image)
  119.         myErr = QTNewGWorld(&myGWorld, kOffscreenPixelType, &myBounds, NULL, NULL, kICMTempThenAppMemory);
  120.         if (myErr != noErr)
  121.             goto bail;
  122.     }
  123.  
  124.     myErr = noErr;
  125.  
  126.     myPixMap = GetGWorldPixMap(myGWorld);
  127.     if (myPixMap != NULL) {
  128.         LockPixels(myPixMap);
  129.         myPictMapAddr = (unsigned long)GetPixBaseAddr(myPixMap);
  130.         
  131.         // get the offset, in bytes, from one row of pixels to the next;
  132.         // according to IM: Imaging With QuickDraw (p. 4-47), the two high-order bits are used as flags,
  133.         // so we need to mask them off (0x3fff == 0b0011 1111 1111 1111)
  134.         myPictRowBytes = (unsigned long)((**myPixMap).rowBytes & 0x3fff);
  135.  
  136.         SetGWorld(myGWorld, NULL);
  137.  
  138.         // create a storage object associated with the new offscreen graphics world
  139.         myStrgPMapPtr = &(**myTexture).fStoragePixmap;
  140.         myStrgPMapPtr->image = Q3MemoryStorage_NewBuffer((void *)myPictMapAddr,
  141.                                                         myPictRowBytes * myBounds.bottom,
  142.                                                         myPictRowBytes * myBounds.bottom);
  143.         myStrgPMapPtr->width        = myBounds.right;
  144.         myStrgPMapPtr->height        = myBounds.bottom;
  145.         myStrgPMapPtr->rowBytes        = myPictRowBytes;
  146.         myStrgPMapPtr->pixelSize    = (**myPixMap).pixelSize;
  147.         myStrgPMapPtr->pixelType    = ((**myPixMap).pixelSize == 16) ? kQ3PixelTypeRGB16 : kQ3PixelTypeRGB32;
  148. // used to be hard-coded:
  149. //        myStrgPMapPtr->pixelSize    = 32;                    // (**myPixMap).pixelSize
  150. //        myStrgPMapPtr->pixelType    = kQ3PixelTypeRGB32;    // ((**myPixMap).pixelSize == 16) ? kQ3PixelTypeRGB16 : kQ3PixelTypeRGB32
  151.         myStrgPMapPtr->bitOrder        = kQ3EndianBig;
  152.         myStrgPMapPtr->byteOrder    = kQ3EndianBig;
  153.     }
  154.     
  155.  
  156.     if (isTextureMovie) {
  157.         TimeBase    myTimeBase;
  158.         
  159.         // start playing the movie in a loop
  160.         SetMovieGWorld((**myTexture).fMovie, myGWorld, GetGWorldDevice(myGWorld));
  161.         GoToBeginningOfMovie((**myTexture).fMovie);
  162.  
  163.         // draw the movie first
  164.         MoviesTask((**myTexture).fMovie, 0);
  165.  
  166.         // throw the movie into loop mode
  167.         myTimeBase = GetMovieTimeBase((**myTexture).fMovie);
  168.         SetTimeBaseFlags(myTimeBase, GetTimeBaseFlags(myTimeBase) | loopTimeBase);
  169.  
  170.         // start playing the movie
  171.         VRMoov_StartMovie((**myTexture).fMovie);        
  172.     } else {
  173.         // draw the picture into the offscreen graphics world
  174.         GraphicsImportSetGWorld(myImporter, myGWorld, NULL);
  175.         GraphicsImportSetBoundsRect(myImporter, &myBounds);
  176.         GraphicsImportDraw(myImporter);
  177.     }
  178.  
  179.     (**myTexture).fpGWorld = myGWorld;
  180.  
  181. bail:
  182.     SetGWorld(myOldGW, myOldGD);
  183.     HUnlock((Handle)myTexture);
  184.  
  185.     if (myImporter != NULL)
  186.         CloseComponent(myImporter);
  187.  
  188.     if (myErr != noErr) {
  189.         if (myTexture != NULL)
  190.             DisposeHandle((Handle)myTexture);
  191.         myTexture = NULL;
  192.     }
  193.         
  194.     return(myTexture);
  195. }
  196.  
  197.  
  198. //////////
  199. //
  200. // VR3DTexture_AddToGroup
  201. // Create a new texture shader based on the pixmap storage data and add it to the group.
  202. //
  203. //////////
  204.  
  205. TQ3Status VR3DTexture_AddToGroup (TextureHdl theTexture, TQ3GroupObject theGroup)
  206. {
  207.     TQ3Status            myStatus = kQ3Failure;
  208.     TQ3StoragePixmap    myStoragePixmap;
  209.     TQ3TextureObject    myTextureObject;
  210.     
  211.     if (theTexture == NULL || theGroup == NULL)
  212.         return(myStatus);
  213.     
  214.     myStoragePixmap = (**theTexture).fStoragePixmap;
  215.     myTextureObject = Q3PixmapTexture_New(&myStoragePixmap);
  216.     if (myTextureObject != NULL) {
  217.  
  218.         TQ3ShaderObject        myTextureShader;
  219.         
  220.         myTextureShader = Q3TextureShader_New(myTextureObject);
  221.         Q3Object_Dispose(myTextureObject);
  222.         
  223.         if (myTextureShader != NULL) {
  224.             TQ3GroupPosition    myPosition = NULL;
  225.             
  226.             // look for an existing texture shader in the group
  227.             Q3Group_GetFirstPositionOfType(theGroup, kQ3SurfaceShaderTypeTexture, &myPosition);
  228.             if (myPosition != NULL) {
  229.             
  230.                 // there is an existing texture shader; just replace it
  231.                 Q3Group_SetPositionObject(theGroup, myPosition, myTextureShader);
  232.             } else {
  233.             
  234.                 // there is no existing texture shader; add one to the group
  235.                 Q3Group_GetFirstPosition(theGroup, &myPosition);
  236.                 Q3Group_AddObjectBefore(theGroup, myPosition, myTextureShader);
  237.             }
  238.             
  239.             Q3Object_Dispose(myTextureShader);
  240.             myStatus = kQ3Success;
  241.         }
  242.     }
  243.  
  244.     return(myStatus);
  245. }
  246.  
  247.  
  248. //////////
  249. //
  250. // VR3DTexture_Delete
  251. // Deallocate the texture.
  252. //
  253. //////////
  254.  
  255. Boolean    VR3DTexture_Delete (TextureHdl theTexture)
  256. {
  257.     PixMapHandle        myPixMap;
  258.  
  259.     if (theTexture == NULL)
  260.         return(false);
  261.  
  262.     HLock((Handle)theTexture);
  263.  
  264.     if ((**theTexture).fMovie != NULL) {
  265.         StopMovie((**theTexture).fMovie);
  266.         DisposeMovie((**theTexture).fMovie);
  267.         (**theTexture).fMovie = NULL;
  268.     }
  269.  
  270.     if ((**theTexture).fpGWorld == NULL) {
  271.         myPixMap = GetGWorldPixMap((**theTexture).fpGWorld);
  272.         if (myPixMap != NULL)
  273.             UnlockPixels(myPixMap);
  274.     
  275.         DisposeGWorld((**theTexture).fpGWorld);
  276.         (**theTexture).fpGWorld = NULL;
  277.     }
  278.  
  279.     if ((**theTexture).fStoragePixmap.image != NULL) {
  280.         Q3Object_Dispose((**theTexture).fStoragePixmap.image);
  281.         (**theTexture).fStoragePixmap.image = NULL;
  282.     }
  283.  
  284.     HUnlock((Handle)theTexture);
  285.     DisposeHandle((Handle)theTexture);
  286.     
  287.     return(true);
  288. }
  289.  
  290.  
  291. //////////
  292. //
  293. // VR3DTexture_NextFrame
  294. // Advance the texture's movie to the next frame.
  295. //
  296. //////////
  297.  
  298. Boolean VR3DTexture_NextFrame (TextureHdl theTexture)
  299. {
  300.     TQ3StoragePixmap    *myStrgPMapPtr;
  301.     long                mySize;
  302.     TQ3Status            myStatus;
  303.     unsigned long        myPictMapAddr;
  304.     PixMapHandle        myPixMap;
  305.  
  306.     // if fpGWorld is non-NULL, then the fMovie is non-NULL and the movie needs updating
  307.     if ((**theTexture).fpGWorld == NULL)
  308.         return(false);
  309.  
  310.     HLock((Handle)theTexture);
  311.  
  312.     if ((**theTexture).fMovie)
  313.         MoviesTask((**theTexture).fMovie, 0);    // draw the next movie frame
  314.  
  315.     myPixMap = GetGWorldPixMap((**theTexture).fpGWorld);
  316.     myStrgPMapPtr = &(**theTexture).fStoragePixmap;
  317.     mySize = myStrgPMapPtr->height * myStrgPMapPtr->rowBytes;
  318.     myPictMapAddr = (unsigned long)GetPixBaseAddr(myPixMap);
  319.  
  320.     // tell QD3D the buffer changed
  321.     myStatus = Q3MemoryStorage_SetBuffer(myStrgPMapPtr->image, (void *)myPictMapAddr, mySize, mySize);
  322.  
  323.     HUnlock((Handle)theTexture);
  324.     
  325.     return(myStatus == kQ3Success);
  326. }
  327.